#!/usr/bin/env bash

find_target_distros() {
	local requested=() supported=() deb="$1" pkg_conf="$2"
	shift 2
	supported=("$@")

	local requested_json i
	for i in "$deb" "*"; do
		if requested_json="$(jq -er --arg target "$i" 'to_entries[] | select(.key == $target).value.Releases' "$pkg_conf")" && [[ $requested_json != "null" ]]; then
			mapfile -t requested < <(jq -er '.[]' <<<"$requested_json") && array_remove "requested" ""
			array_intersect "${supported[@]}" -- "${requested[@]}"
			return
		fi
	done

	if [[ $RSDK_OPTION_DEFAULT_DISTRO == "true" ]]; then
		echo "${supported[0]}"
	fi
}

download_pkgs() {
	local RSDK_TEMP i DISTROS=("$@") OUTPUT="$RSDK_OPTION_DEB_DIR"
	RSDK_TEMP="$(mktemp -d)"
	for i in "${DISTROS[@]}"; do
		mkdir -p "$OUTPUT/$i"
	done

	for i in "${!RSDK_PKG_REPO_ARRAY[@]}"; do
		request_parallel
		(
			org="$RSDK_PACKAGE_ORG"
			pkg="${RSDK_PKG_REPO_ARRAY[i]}"
			tag="${RSDK_PKG_REPO_TAG_ARRAY[i]}"

			echo "Downloading '$org/$pkg@$tag'..."
			mkdir -p "$RSDK_TEMP/$pkg"

			if [[ $RSDK_OPTION_DRY_RUN == "false" ]]; then
				gh release download "$tag" --repo "$org/$pkg" --dir "$RSDK_TEMP/$pkg"
				if [[ ! -f "$RSDK_TEMP/$pkg/pkg.conf" ]] && [[ $RSDK_OPTION_DEFAULT_DISTRO == "true" ]]; then
					cp "$RSDK_TEMP/$pkg"/*.deb "$OUTPUT/${DISTROS[0]}"
				else
					for j in "$RSDK_TEMP/$pkg"/*.deb; do
						mapfile -t targets < <(find_target_distros "$(basename "$j")" "$RSDK_TEMP/$pkg/pkg.conf" "${DISTROS[@]}") && array_remove "targets" ""
						for k in "${targets[@]}"; do
							cp "$j" "$OUTPUT/$k"
						done
					done
				fi
			fi
		) &
	done
	wait_parallel

	rm -rf "$RSDK_TEMP"
}

main() {
	local SCRIPT_DIR
	SCRIPT_DIR="$(dirname "$(realpath "$0")")"
	# shellcheck source=src/lib/rsdk/utils.sh
	source "$SCRIPT_DIR/../../lib/rsdk/utils.sh"
	# shellcheck source=src/lib/rsdk/stdlib.sh
	source "$SCRIPT_DIR/../../lib/rsdk/stdlib.sh"

	local TEMP
	if ! TEMP="$(getopt -o "hd" -l "help,dry-run,deb-dir:,no-default-distro" -n "$0" -- "$@")"; then
		return
	fi
	eval set -- "$TEMP"

	export RSDK_OPTION_DRY_RUN="${RSDK_OPTION_DRY_RUN:-false}"
	export RSDK_PACKAGE_ORG="${RSDK_PACKAGE_ORG:-$("$SCRIPT_DIR/../../bin/rsdk" config infra.organizations.package)}"
	export RSDK_PKG_REPO_ARRAY=("${RSDK_PKG_REPO_ARRAY[@]}")
	export RSDK_PKG_REPO_TAG_ARRAY=("${RSDK_PKG_REPO_TAG_ARRAY[@]}")
	export RSDK_OPTION_DEB_DIR="${RSDK_OPTION_DEB_DIR:-${TMPDIR:-/tmp}/rsdk-deb}"
	export RSDK_OPTION_DEFAULT_DISTRO="${RSDK_OPTION_DEFAULT_DISTRO:-true}"

	mapfile -t RSDK_PKG_REPO_ARRAY < <(jq -er 'to_entries[].key' pkgs.json) && array_remove "RSDK_PKG_REPO_ARRAY" ""
	mapfile -t RSDK_PKG_REPO_TAG_ARRAY < <(jq -er 'to_entries[].value' pkgs.json) && array_remove "RSDK_PKG_REPO_TAG_ARRAY" ""

	while true; do
		TEMP="$1"
		shift
		case "$TEMP" in
		-d | --dry-run)
			RSDK_OPTION_DRY_RUN="true"
			;;
		-h | --help)
			TEMP="$(basename "$0")"
			rsdk help "${TEMP#rsdk-}"
			return
			;;
		--deb-dir)
			RSDK_OPTION_DEB_DIR="$1"
			shift
			;;
		--no-default-distro)
			RSDK_OPTION_DEFAULT_DISTRO="false"
			;;
		--)
			break
			;;
		*)
			error "$EXIT_UNKNOWN_OPTION" "$TEMP"
			;;
		esac
	done

	if (($# == 0)); then
		"$0" --help
		return
	fi

	download_pkgs "$@"
}

main "$@"
